﻿// Decompiled with JetBrains decompiler
// Type: Netick.ReliableChannel`1
// Assembly: Netick, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 6726ECA1-C773-4CF7-8952-E81B30D93B52
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.dll
// XML documentation location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.xml

using System.Collections.Generic;

#nullable disable
namespace Netick;

internal abstract class ReliableChannel<T> : NetworkChannel where T : ISerializableMessage
{
  internal const int MaxMsgsPerSend = 1024 /*0x0400*/;
  private Queue<ReliableChannel<T>.ReliableMsg> _outgoingMsgs = new Queue<ReliableChannel<T>.ReliableMsg>(64 /*0x40*/);
  private List<T> _pendingMsgs = new List<T>(64 /*0x40*/);
  private SequenceId _ackMsgId = SequenceId.INVALID;
  private SequenceId _lastQueuedMsgId;

  public ReliableChannel(NetickEngine engine, NetworkConnection connection)
    : base(engine, connection)
  {
  }

  public override void Reset()
  {
    this._ackMsgId = SequenceId.INVALID;
    this._lastQueuedMsgId = SequenceId.START.Next;
    while (this._outgoingMsgs.Count > 0)
      this._outgoingMsgs.Dequeue().Msg.UnregisterConnection(this.Connection);
    this._outgoingMsgs.Clear();
  }

  public void EnqueueMsg(T msg)
  {
    msg.RegisterConnection(this.Connection, 1);
    this._outgoingMsgs.Enqueue(new ReliableChannel<T>.ReliableMsg(msg, this._lastQueuedMsgId));
    this._lastQueuedMsgId = this._lastQueuedMsgId.Next;
  }

  public override void Write(BitBuffer buffer)
  {
    SequenceId sequenceId = SequenceId.INVALID;
    if (this._outgoingMsgs.Count > 0)
      sequenceId = this._outgoingMsgs.Peek().Id;
    buffer.AddUInt(this._ackMsgId.RawValue);
    buffer.AddUInt(sequenceId.RawValue);
    int num1 = this.Engine.Config.MaxDataPerConnectionPerTickInBytes - 100;
    uint num2 = 0;
    int writePos1 = buffer.WritePos;
    buffer.Add(20, 0U);
    this._pendingMsgs.Clear();
    foreach (ReliableChannel<T>.ReliableMsg outgoingMsg in this._outgoingMsgs)
      this._pendingMsgs.Add(outgoingMsg.Msg);
    int count = this._outgoingMsgs.Count;
    for (int index = 0; index < count && num2 != 1024U /*0x0400*/; ++index)
    {
      ReliableChannel<T>.ReliableMsg reliableMsg = this._outgoingMsgs.Peek();
      if (buffer.Length() + reliableMsg.Msg.SizeBytes < num1)
      {
        int writePos2 = buffer.WritePos;
        this._pendingMsgs[index].Write(this.Connection, buffer);
        if (buffer.Length() > num1)
        {
          buffer.WritePos = writePos2;
          break;
        }
        ++num2;
      }
      else
        break;
    }
    buffer.Insert(writePos1, 20, num2);
  }

  public override void Read(BitBuffer buffer)
  {
    SequenceId sequenceId1 = new SequenceId(buffer.ReadUInt());
    SequenceId sequenceId2 = new SequenceId(buffer.ReadUInt());
    uint num1 = buffer.Read(20);
    for (int index = 0; (long) index < (long) num1; ++index)
    {
      int msgId = buffer.ReadInt4();
      SequenceId sequenceId3 = sequenceId2 + index;
      bool invoke = false;
      SequenceId ackMsgId = this._ackMsgId;
      if (sequenceId3 > ackMsgId || !this._ackMsgId.IsValid)
      {
        invoke = true;
        this._ackMsgId = sequenceId2 + index;
      }
      this.Read(buffer, msgId, invoke);
    }
    if (!sequenceId1.IsValid || !this._lastQueuedMsgId.IsValid || !sequenceId1.IsValid)
      return;
    int num2 = this._outgoingMsgs.Count - (this._lastQueuedMsgId - sequenceId1) + 1;
    for (int index = 0; index < num2; ++index)
      this._outgoingMsgs.Dequeue().Msg.RegisterSent(this.Connection);
  }

  protected abstract void Read(BitBuffer buffer, int msgId, bool invoke);

  public struct ReliableMsg(T msg, SequenceId id)
  {
    public T Msg = msg;

    public SequenceId Id { get; set; } = id;
  }
}
